#include "xShaderParameter.h"
#include "xTexture.h"
#include "xTextureManager.h"


namespace XE	
{

	xShaderParameter::xShaderParameter(const  xString&name/*,xShader* pShader*/)
		:m_Name(name),/*m_pShader(pShader),*/m_type(XSPT_UNSUPPORTED),m_Size(0),m_pData(NULL),m_IsUpDateAnno(false)
	{

	}


	xShaderParameter::xShaderParameter(const xShaderParameter& para)	
		:m_Name(para.GetName()),m_type(para.GetType()),m_Size(para.GetSize())
	{
		if(m_Size!=NULL)
		{
			m_pData = new char[m_Size];
			memcpy(m_pData,para.GetData(),m_Size);
		}

	}

	void xShaderParameter::AddAnnotations(const xString& name,const xString& Value)
	{
		m_AnnotationMap.insert(std::make_pair(name,Value));
		m_IsUpDateAnno = true;
		return ;
	}

	void xShaderParameter::upDateAnnotation()
	{
		if(m_type==XSPT_TEXTURE)
		{
			ParaMap::iterator nameit =  m_AnnotationMap.find("name");


			if(nameit!=m_AnnotationMap.end())
			{
				xTexturePtr pTexture = xTextureManager::getSingleton().GetByName(nameit->second);
				if(pTexture.isNull())
				{ 
					xVector2 size(256,256);
					ParaMap::iterator sizeit = m_AnnotationMap.find("TextureSize");
					if(sizeit!=m_AnnotationMap.end())
					{
						size = xHelp::StringToVector2(sizeit->second);
					}
					ParaMap::iterator typeit =  m_AnnotationMap.find("TextureType");
					if(typeit!=m_AnnotationMap.end())
					{
						if(typeit->second=="RenderTextre")
						{
							pTexture = xTextureManager::getSingleton().CreateRenderTexture(nameit->second,size.x,size.y);
						}else
						{
							pTexture=xTextureManager::getSingleton().CreateResource(nameit->second,nameit->second);

						}

					}else
					{
						pTexture=xTextureManager::getSingleton().\
							CreateResource(nameit->second,nameit->second);
					}


				}

				ParaMap::iterator normalit = m_AnnotationMap.find("NormalMap");
				if(normalit!=m_AnnotationMap.end()&&pTexture.isNull())
				{
					pTexture = xTextureManager::getSingleton().CreateNormalTexture(nameit->second+"normal",pTexture);

				}

				if(pTexture.isNull()==false)
				{
					int data = (int)(pTexture->GetRealData());
					WriteData(&data,sizeof(int));


				}


			}

		}

		m_IsUpDateAnno = false;

	}

	xShaderParameter& xShaderParameter::operator=(const xShaderParameter& para)
	{
		if(m_pData!=NULL)
		{
			delete [] m_pData;
			m_pData=NULL;
		}

		m_Name=para.GetName();
		m_type=para.GetType();
		m_Size=para.GetSize();

		if(m_Size!=NULL)
		{
			m_pData = new char[m_Size];
			memcpy(m_pData,para.GetData(),m_Size);
		}

		return *this;

	}


		  void xShaderParameter::SetAnnotationMap( const  ParaMap&  para )
		  {
			  m_AnnotationMap = para;
			  m_IsUpDateAnno = true;
		  }


	void xShaderParameter::SetSize(UINT size)
	{
		if(size==m_Size)
			return ;
		if(m_pData!=NULL)
		{
			delete [] m_pData;
			m_pData = new char[size];
		}
		m_Size = size;
		return ;
	}





	AutoConstantDef AutoConstantParameter::m_AutonList[]=
	{
		AutoConstantDef(ACT_WORLD_MATRIX,         "WORLD",                    XSPT_FLOAT,   sizeof(float)*16),
		AutoConstantDef(ACT_VIEW_MATRIX,          "VIEW",                     XSPT_FLOAT,   sizeof(float)*16),
		AutoConstantDef(ACT_INVSER_VIEW_MATRIX,    "VIEWINV",              XSPT_FLOAT,   sizeof(float)*16),


		AutoConstantDef(ACT_PROJECTION_MATRIX,    "PROJECTION",               XSPT_FLOAT,   sizeof(float)*16),
		AutoConstantDef(ACT_VIEWPROJ_MATRIX,      "VIEWPROJECTION",           XSPT_FLOAT,   sizeof(float)*16),
		AutoConstantDef(ACT_WORLDVIEW_MATRIX,     "WORLDVIEW",                XSPT_FLOAT,   sizeof(float)*16),
		AutoConstantDef(ACT_WORLDVIEWPROJ_MATRIX, "WORLDVIEWPROJECTION",      XSPT_FLOAT,   sizeof(float)*16),

		AutoConstantDef(ACT_WORLD_MATRIX_ARRAY,    "WORLDMATRIXARRAY",         XSPT_FLOAT ,   sizeof(float)*16*26),

		AutoConstantDef(ACT_TEXTURE_0,            "Texture0",                       XSPT_TEXTURE, sizeof(int) ),
		AutoConstantDef(ACT_TEXTURE_1,            "Texture1",                       XSPT_TEXTURE, sizeof(int) ),
		AutoConstantDef(ACT_TEXTURE_2,            "Texture2",                       XSPT_TEXTURE, sizeof(int) ),
		AutoConstantDef(ACT_TEXTURE_3,            "Texture3",                       XSPT_TEXTURE, sizeof(int) ),
		AutoConstantDef(ACT_TEXTURE_4,            "Texture4",                       XSPT_TEXTURE, sizeof(int) ),
		AutoConstantDef(ACT_TEXTURE_5,            "Texture5",                       XSPT_TEXTURE, sizeof(int) ),
		AutoConstantDef(ACT_TEXTURE_6,            "Texture6",                       XSPT_TEXTURE, sizeof(int) ),
		AutoConstantDef(ACT_TEXTURE_7,            "Texture7",                       XSPT_TEXTURE, sizeof(int) ),



	};


	AutoConstantParameter::AutoConstantParameter(const xString& name,AutoConstantType AutoContType)
		:xShaderParameter(name),m_AutoType(AutoContType)
	{

		UINT size = (sizeof(m_AutonList))/(sizeof(AutoConstantDef));
		for(UINT i = 0;i<size;++i)
		{
			if(m_AutonList[i].m_AutoConstantType==m_AutoType)
			{
				SetSize(m_AutonList[i].m_size);
				SetSemantic(m_AutonList[i].m_SemanticName);
				SetType(m_AutonList[i].m_ShaderparentType);
				return ;
			}
		}
		xLogMessager::getSingleton().logMessage("Create AutoConstanParameter fail,can't find AutoType");
		throw("Create AutoConstanParameter fail,can't find AutoType");

	}


	bool AutoConstantParameter::IsAutoConstantPara(const  xString& SemanticName)
	{
		UINT size = (sizeof(m_AutonList))/(sizeof(AutoConstantDef));
		for(UINT i = 0;i<size;++i)
		{
			if(m_AutonList[i].m_SemanticName==SemanticName)
				return true;
		}
		return false;
	}


	AutoConstantType AutoConstantParameter::GetAutoType(const xString& sematicName)
	{
		UINT size = (sizeof(m_AutonList))/(sizeof(AutoConstantDef));
		for(UINT i = 0;i<size;++i)
		{
			if(m_AutonList[i].m_SemanticName==sematicName)
				return m_AutonList[i].m_AutoConstantType;
		}
		return ACT_UNKNOW;

	}

}